(function($) {
	$
			.widget(
					"ui.combobox",
					{
						options : {
							error : {}
						},
						
						_create : function() {
							var self = this, select = this.element.hide(), selectedId = select.prop('id'), selected = select
									.children(":selected"), value = selected
									.val() ? selected.text() : "";
							var input = this.input = $("<input>").prop('id', selectedId + '_combobox').prop('name', selectedId + '_combobox')
									.insertAfter(select)
									.val(value)
									.addClass(
											"ui-widget-content ui-corner-all ui-combobox-input")
									.autocomplete(
											{
												delay : 0,
												minLength : 0,
												source : function(request,
														response) {
													var matcher = new RegExp(
															$.ui.autocomplete
																	.escapeRegex(request.term),
															"i");
													response(select
															.children("option")
															.map(
																	function() {
																		var text = $(
																				this)
																				.text();
																		if (this.value
																				&& (!request.term || matcher
																						.test(text)))
																			return {
																				label : text
																						.replace(
																								new RegExp(
																										"(?![^&;]+;)(?!<[^<>]*)("
																												+ $.ui.autocomplete
																														.escapeRegex(request.term)
																												+ ")(?![^<>]*>)(?![^&;]+;)",
																										"gi"),
																								"<strong>$1</strong>"),
																				value : text,
																				option : this
																			};
																	}));
												},
												select : function(event, ui) {
													ui.item.option.selected = true;
													self
															._trigger(
																	"selected",
																	event,
																	{
																		item : ui.item.option
																	});
													select.trigger("change");
												},
												change : function(event, ui) {
													if (!ui.item) {
														var value = $(this)
																.val();
														var matcher = new RegExp(
																"^"
																		+ $.ui.autocomplete
																				.escapeRegex($(
																						this)
																						.val())
																		+ "$",
																"i"), valid = false;
														select
																.children(
																		"option")
																.each(
																		function() {
																			if ($(
																					this)
																					.text()
																					.match(
																							matcher)) {
																				this.selected = valid = true;
																				return false;
																			}
																		});
														if (!valid) {
															// remove invalid
															// value, as it
															// didn't match
															// anything
															$(this)
																	.val("")
																	.attr(
																			"title",
																			value
																					+ " didn't match any item")
																	.tooltip(
																			"open");
															select.val("");
															if($.isFunction(self.options.error)) {
																self.options.error.call();
															}
															setTimeout(
																	function() {
																		input
																				.tooltip(
																						"close")
																				.attr(
																						"title",
																						"");
																	}, 2500);
															input
																	.data("ui-autocomplete").term = "";
															return false;
														}
													}
												}
											})
									.addClass(
											"ui-widget ui-widget-content ui-corner-left");
							var tabIndex = select.prop('tabindex');
							if(tabIndex != '') {
								input.prop('tabindex', tabIndex);
							}
							input.data("ui-autocomplete")._renderItem = function(
									ul, item) {
								return $("<li></li>").data("ui-autocomplete-item",
										item).append(
										"<a>" + item.label + "</a>").appendTo(
										ul);
							};

							input.tooltip({
								position : {
									of : this.button
								},
								tooltipClass : "ui-state-highlight"
							});

							this.button = $(
									"<button type='button'>&nbsp;</button>")
									.attr("tabIndex", -1)
									.attr("title", "Show All Items")
									.insertAfter(input)
									.button({
										icons : {
											primary : "ui-icon-triangle-1-s"
										},
										text : false
									})
									.removeClass("ui-corner-all")
									.addClass("ui-corner-right ui-button-icon")
									.click(
											function() {
												// close if already visible
												if (input
														.autocomplete("widget")
														.is(":visible")) {
													input.autocomplete("close");
													return;
												}

												// pass empty string as value to
												// search for, displaying all
												// results
												input
														.autocomplete("search",
																"");
												input.focus();
											});
						},

						destroy : function() {
							this.input.remove();
							this.button.remove();
							this.element.show();
							$.Widget.prototype.destroy.call(this);
						}
					});
})(jQuery);